package p.ithorns.example.task;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * ScheduleService
 *
 * @author Ht.L
 * @date 2024-05-11 21:54
 * @since 1.0.0
 */
@Slf4j
@Service
public class ScheduleService {

    // private final static int EARLY_MINUTE = 1;

    private final List<Task> tasks = new ArrayList<>();

    private final Plan plan;

    public ScheduleService() {
        plan = new Plan();
        plan.setCycleUnit(CycleUnit.MINUTE.getCode());
        LocalDateTime init = LocalDateTime.now().plusMinutes(1);
        plan.setInitTime(init);
        plan.setExecTime(null);
        plan.setCycle(1);
        plan.setDailyTasks(3);
        plan.setSchedule(1);

        log.info("初始执行时间：{}", init);
    }

    // @Async
    // @Scheduled(cron = "0 0/1 * * * ?")
    public void expiredDetection() {
        final LocalDateTime now = LocalDateTime.now();
        System.out.println();
        log.info("======> {} 任务过期检测...", now);
        for (Task task : tasks) {
            if (task.isExpired()) {
                continue;
            }

            TaskExpiryParam param = new TaskExpiryParam()
                    .setCurrent(now)
                    .setCreateTime(task.getCreateTime())
                    .setCycleUnit(task.getCycleUnit())
                    .setSchedule(task.getSchedule());

            TaskDetector.detection4TaskExpiration(param, (expiration) -> {
                task.setExpired(true);
                log.info("Task.过期");
            });
        }
    }

    @Async
    @Scheduled(cron = "0 * * * * ?")
    public void schedule() {
        LocalDateTime now = LocalDateTime.now();
        System.out.println();
        log.info("======> {} 定时调度...", now);

        TaskDetectionParam param = new TaskDetectionParam()
                .setInit(plan.getInitTime())
                .setLast(plan.getExecTime())
                .setCurrent(now)
                .setCycleUnit(plan.getCycleUnit())
                .setCycle(plan.getCycle())
                .setDailyTasks(plan.getDailyTasks())
                .setExecCount(plan.getExecCount());

        log.info("执行参数：{}", param.toString());
        TaskDetector.detectionExpiry4Creation(param, this::doSomething);
    }

    private void doSomething(TaskDetectionParam out) {
        log.info("--> 触发执行 ");

        log.info("创建任务。。。");
        Task task = new Task();
        task.setCreateTime(LocalDateTime.now());
        task.setSchedule(plan.schedule);
        task.setCycleUnit(plan.getCycleUnit());

        // 更新计划
        LocalDateTime execTime = out.getLast();

        task.setInitTime(execTime);
        CycleUnit cycleUnit = CycleUnit.get(plan.getCycleUnit());
        if (null != cycleUnit) {
            task.setEndTime(cycleUnit.plusCycle(execTime, plan.getSchedule()));
        }
        tasks.add(task);


        plan.setExecTime(execTime);

        int execCount = out.getExecCount();
        plan.setExecCount(execCount);
        log.info("--> 更新执行时间: {}, 执行次数: {}, 本次任务执行时间：{}, 本次任务截止时间：{}",
                execTime, execCount, task.getInitTime(), task.getEndTime());
    }


    /**
     * 业务对象
     */
    @Data
    static class Plan {

        private LocalDateTime initTime;

        private LocalDateTime execTime;

        String cycleUnit;

        int cycle;

        Integer dailyTasks;

        int execCount;

        int schedule;
    }

    @Data
    static class Task {

        LocalDateTime createTime;

        boolean expired;

        String cycleUnit;

        int schedule;

        private LocalDateTime initTime;

        private LocalDateTime endTime;
    }

}